(function(window) {

	Types.exportSymbol("js.com.sandwormz.Message.deserialize", deserialize);

	Types.exportSymbol("js.com.sandwormz.Message.newGetMessage", newGetMessage);
	Types.exportSymbol("js.com.sandwormz.Message.newPutMessage", newPutMessage);
	Types.exportSymbol("js.com.sandwormz.Message.newSyncMessage", newSyncMessage);
	
	/**
	 * get the local document and return the text and filename.
	 *   if the local document doesn't exist, a new empty one 
	 *   will be created.
	 */
	Types.exportSymbol("js.com.sandwormz.Message.GET_TYPE", "get");
	
	/**
	 * put the specified document. will rewrite any documents already
	 *   existing.
	 */
	Types.exportSymbol("js.com.sandwormz.Message.PUT_TYPE", "put");
	
	Types.exportSymbol("js.com.sandwormz.Message.SYNC_TYPE", "sync");
	Types.exportSymbol("js.com.sandwormz.Message.ACK_TYPE", "ack");
	
	Types.exportSymbol("js.com.sandwormz.Message.ID_PROPERTY", "id");
	Types.exportSymbol("js.com.sandwormz.Message.TYPE_PROPERTY", "type");
	Types.exportSymbol("js.com.sandwormz.Message.PATCH_PROPERTY", "patch");
	Types.exportSymbol("js.com.sandwormz.Message.FILENAME_PROPERTY", "filename");
	Types.exportSymbol("js.com.sandwormz.Message.CONTENT_PROPERTY", "content");
	
	var id = 0;
	
	//static method
	function deserialize(string) {
		var message = new Message({
			fromString:string
		});
		
		return message;
	}
	
	/**
	 * 
	 * @expose
	 */
	function newSyncMessage(patch) {
		Assert.assertNotNull(patch);
		
		var message = new Message({
			type:js.com.sandwormz.Message.SYNC_TYPE
		});
		message.setProperty(js.com.sandwormz.Message.PATCH_PROPERTY, patch);
		
		return message;
	}
	/**
	 * 
	 * @expose
	 */
	function newGetMessage() {
		var message = new Message({
			type:js.com.sandwormz.Message.GET_TYPE
		});
				
		return message;		
	}
	
	function newPutMessage(filename, content) {
		var message = new Message({
			type:js.com.sandwormz.Message.PUT_TYPE
		});
		message.setProperty(js.com.sandwormz.Message.FILENAME_PROPERTY, filename);
		message.setProperty(js.com.sandwormz.Message.CONTENT_PROPERTY, content);
		return message;		
	}
	
	/**
	 * 
	 * @expose
	 */
	function Message(config) {
		var properties = {};
		if(! config.fromString) {
			Assert.assert(config.type, "A message may only be created with a type.");
		
			properties[js.com.sandwormz.Message.ID_PROPERTY] = id++;
			properties[js.com.sandwormz.Message.TYPE_PROPERTY] = config.type;
		} else {
			deserialize(config.fromString);
		}
		var that = {};

		that.publicMethods = {
			getId : function() {},
			getType : function() {},
			getProperty : function(key) {},
			setProperty : function(key, value) {},
			serialize : function() {}
		};
		
		that.publicMethods.getId = function(key) {
			return that.publicMethods.getProperty(js.com.sandwormz.Message.ID_PROPERTY);
		};
		that.publicMethods.getType = function(key) {
			return that.publicMethods.getProperty(js.com.sandwormz.Message.TYPE_PROPERTY);
		};
		
		that.publicMethods.getProperty = function(key) {
			return properties[key];
		};
		
		that.publicMethods.setProperty = function(key, value) {
			Assert.assert(key != 'id', "Can't change the id");
			Assert.assert(key != 'type', "Can't change the type");
			
			properties[key] = value;
		};
		
		that.publicMethods.serialize = function serialize() {
			var serialized = JSON.stringify(properties, null, 2);
			return serialized;
		};
		
		function deserialize(string) {
			properties = JSON.parse(string);
		};

		return that.publicMethods;
	};
})(this);
